function [values, distinctHeaderValues, varargout] = makeArrayFromCSV(fileName, NumHeaderCols, varargin)
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% This function reads a CSV file where the first N columns are "headers" (user-id, week-id, product-id, ...),
	% and all the other column are numeric values. Each combination of id's should be unique (there should be at most
	% one row for a given combination of id's).
	%
	% The function finds the unique id's (distinctHeaderValues) (or reads them as arguments if passed as arguments),
	% and then fills an array with the values given for each row of the CSV file. If a combination of id's does not
	% appear in the CSV file, a default value is entered (0 by default).
	%
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	%%%%% Inputs:
	% fileName:								
	% NumHeaderCols:						integer (number of columns that are "labels" - not "numeric" data)string
	% varargin{1}: columnTypes:							cell(NumCols, 1):
	%	values can be 'double', 'char', ...
	% varargin{2}: defaultValue:			scalar
	% varargin{3}: distinctHeaderValues:	cell(NumHeaderCols, 1) of cells of strings (or numbers)
	%	If I pass this argument, it does not need to be "full", in the sense that I may give the distinct header values
	%	for some header columns but not for others: if for a given column, I pass some distinct header values, then
	%	these values will be used; if for a column the list of distinct header values passed is empty (length=0), then
	%	the script will find those distinct header values by looking at the column.
	%	This can be handy for example if I have a user-id and a week-id: I want all week-id's from 1 to X without holes;
	%	however I don't want to pass a priori the list of all user-id's.
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	%%%%% Outputs:
	% values:								NumDistinctHeaders1 x NumDistinctHeaders2 x ... x NumDistinctHeadersN
	% distinctHeaderValues:					cell(NumHeaderCols, 1) of strings
	% VarNames:								cell(2,1):
	%	{1}:									cell(NumHeaderCols, 1) of strings
	%	{2}:									cell(NumCols-NumHeaderCols, 1) of strings
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	%%%% Read arguments
	if nargin >= 3
		columnTypes = varargin{1};
	else	
		columnTypes = {};
	end
	if nargin >= 4
		defaultValue = varargin{2};
	else	
		defaultValue = 0;
	end
	if nargin >= 5
		distinctHeaderValues = varargin{3};
	else	
		distinctHeaderValues = {};
	end
	
	% Read table
	opts = detectImportOptions(fileName);
	if length(columnTypes) > 0
		for jj = 1:length(columnTypes)
			opts = setvartype(opts, opts.VariableNames{jj}, columnTypes{jj});
		end
	end
	if exist('opts')
		M = readtable(fileName, opts);
	else
		M = readtable(fileName);
	end
	NumRows = size(M, 1);
	NumCols = size(M, 2);
	NumVars = NumCols - NumHeaderCols;
	
	if nargout >= 3
		VarNames{1} = M.Properties.VariableNames(1:NumHeaderCols);
		VarNames{2} = M.Properties.VariableNames(NumHeaderCols+1:NumCols);
		varargout{1} = VarNames;
	end
	
	
	% Get unique values for each header column (assumes that the headers are the first columns on the left)
	if length(distinctHeaderValues) == 0
		distinctHeaderValues = cell(NumHeaderCols, 1);
	end
	mydims = zeros(1, NumHeaderCols);
	for jj=1:NumHeaderCols
		if length(distinctHeaderValues{jj}) == 0
			distinctHeaderValues{jj} = sort(table2array(unique(M(:,jj))));
		end
		mydims(jj) = length(distinctHeaderValues{jj});
	end
	
	% Create array
	if defaultValue ~= 0
		values = defaultValue * ones([mydims NumVars]);
	else
		values = zeros([mydims NumVars]);
	end
	
	% Get types of each variable in the table
	VariableTypes = varfun(@class,M,'OutputFormat','cell');
	
	% Fill array
	tic
	for kk = 1:NumRows
		idces = zeros(1, NumHeaderCols);
		for jj = 1:NumHeaderCols
		    header_jk = M(kk,jj);
			if strcmp(VariableTypes{jj}, 'char') | strcmp(VariableTypes{jj}, 'cell')
				idces(jj) = find(ismember(distinctHeaderValues{jj}, table2cell(header_jk)));
			else if strcmp(VariableTypes{jj}, 'double')
				idces(jj) = find(distinctHeaderValues{jj} == table2array(header_jk));
			end
			end
		end
		for vv = 1:NumVars
			values(sub2ind_ludo([mydims NumVars], [idces vv])) = table2array(M(kk,jj+vv));
		end
		displayRemainingTime(kk, NumRows, 1000);
	end
end
